package com.jojo.bubble.utils;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
//import com.github.wxpay.sdk.WXPayConstants;
//import com.github.wxpay.sdk.WXPayUtil;
import com.jojo.bubble.common.handle.WxPayConfig;
import com.jojo.bubble.entity.Order;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.security.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author JoJo
 * @Date 2021/12/6 1:19
 * @Description
 * @Version 1.0
 */

@Slf4j
public class WeChatUtil {

    public static final String appid = "wxf8b0b094c3b35cab";

    public static final String secret = "8c3ec344559b4134be54147471aea7de";

    private static final String mchId = "1605643694";

    private static final String weixinKey = "apikeyforzhinengcheliang20210112";

    private static final String unifiedorderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    private static Config config = null;

    private static JsapiServiceExtension jsapiService = null;

    public static JSONObject getSessionKeyOrOpenId(String code) {
        String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
        HashMap<String, Object> requestUrlParam = new HashMap<>();
        //小程序appId
        requestUrlParam.put("appid", appid);
        //小程序secret
        requestUrlParam.put("secret", secret);
        //小程序端返回的code
        requestUrlParam.put("js_code", code);
        //默认参数
        requestUrlParam.put("grant_type", "authorization_code");
        //发送post请求读取调用微信接口获取openid用户唯一标识
        String result = HttpUtil.get(requestUrl, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        return jsonObject;
    }

    public static JSONObject getAccessToken() {
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/token";
        HashMap<String, Object> requestUrlParam = new HashMap<>();
        //小程序appId
        requestUrlParam.put("appid", appid);
        //小程序secret
        requestUrlParam.put("secret", secret);
        //默认参数
        requestUrlParam.put("grant_type", "client_credential");
        //发送post请求读取调用微信接口获取accessToken
        String result = HttpUtil.get(requestUrl, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        return jsonObject;
    }

    public static JSONObject getPublicUserInfo(String token,String openId) {
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info";
        HashMap<String, Object> requestUrlParam = new HashMap<>();
        //小程序appId
        requestUrlParam.put("access_token", token);
        //小程序secret
        requestUrlParam.put("openid", openId);
        //默认参数
        requestUrlParam.put("lang", "zh_CN");

        String result = HttpUtil.get(requestUrl, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        return jsonObject;
    }

    public static JSONObject getQrcode(String token, Integer id) {
        String requestUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + token;
        HashMap<String, Object> requestUrlParam = new HashMap<>();
        requestUrlParam.put("scene", "id=1");
        requestUrlParam.put("page", "pages/index/index");
        requestUrlParam.put("check_path", false);
        requestUrlParam.put("env_version", "release");

        String result = HttpUtil.post(requestUrl, requestUrlParam);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        return jsonObject;
    }



    public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONUtil.parseObj(result);
            }
        } catch (Exception e) {
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        JSONObject jsonObject = getAccessToken();
        System.out.println("token:" + jsonObject);
//        String buffer = getMiniQrcode("a=1",token);
//        System.out.println("buffer" + buffer);
    }

    public static String getMiniQrcode(String sceneStr, String accessToken) {
        RestTemplate rest = new RestTemplate();
        InputStream inputStream = null;
        OutputStream outputStream = null;
        byte[] result = null;
        String codeUrl = null;
        ResponseEntity<byte[]> entity = null;
        File file = null;
        try {
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
            Map<String, Object> param = new HashMap<>();
            param.put("scene", sceneStr);
            param.put("page", "pages/index/index");
            param.put("width", 430);
            param.put("is_hyaline", true);
            param.put("auto_color", false);
            Map<String, Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            param.put("line_color", line_color);
//            LOG.info("调用生成微信URL接口传参:" + param);
            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            HttpEntity requestEntity = new HttpEntity(param, headers);
            entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
//            LOG.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
            result = entity.getBody();
            System.out.println("result:" + result);

            inputStream = new ByteArrayInputStream(result);
            String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + sceneStr.split("=")[1] + ".png";
            file = new File("D:/fileUpload/"+ fileName);
//            file = new File("/root/source/" + fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            outputStream = new FileOutputStream(file);
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf, 0, 1024)) != -1) {
                outputStream.write(buf, 0, len);
            }
            outputStream.flush();
            codeUrl = "https://jblhsx.ahwrxx.com/image/" + fileName;
        } catch (Exception e) {
            System.out.println("调用小程序生成微信永久小程序码URL接口异常" + e);
//            LOG.error("调用小程序生成微信永久小程序码URL接口异常",e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return codeUrl;
    }

    public static HashMap<String, String> jsapiPayV3(String out_trade_no, Integer money, String openid, String description) throws IOException {
        InputStream inputStream = WeChatUtil.class.getClassLoader().getResourceAsStream("cert/apiclient_key.pem");
        File tempFile = File.createTempFile("apiclient_key", ".pem");
        tempFile.deleteOnExit();
        try (OutputStream out = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        String filePath = tempFile.getAbsolutePath();
        if (config == null) {
            config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(WxPayConfig.mchId)
                    .privateKeyFromPath(filePath)
                    .merchantSerialNumber(WxPayConfig.merchantSerialNumber)
                    .apiV3Key(WxPayConfig.apiV3key)
                    .build();
        }
        if (jsapiService == null) {
            jsapiService = new JsapiServiceExtension.Builder().config(config).build();
        }

        Amount amount = new Amount();
        amount.setTotal(money);
        Payer payer = new Payer();
        payer.setOpenid(openid);

        PrepayRequest preRequest = new PrepayRequest();
        preRequest.setAmount(amount);
        preRequest.setAppid(WxPayConfig.appId);
        preRequest.setMchid(WxPayConfig.mchId);
        preRequest.setDescription(description);
        preRequest.setNotifyUrl(WxPayConfig.notifyUrl);
        preRequest.setOutTradeNo(out_trade_no);
        preRequest.setPayer(payer);
        PrepayWithRequestPaymentResponse responses = jsapiService.prepayWithRequestPayment(preRequest);
//        System.out.println(responses);
        HashMap<String, String> payParameters = new HashMap<>();
        payParameters.put("appId", WxPayConfig.appId);
        payParameters.put("timeStamp", responses.getTimeStamp());
        payParameters.put("package", responses.getPackageVal());
        payParameters.put("nonceStr", responses.getNonceStr());
        payParameters.put("signType", responses.getSignType());
        payParameters.put("paySign", responses.getPaySign());

        return payParameters;
    }


//    public static HashMap<String, String> appletPay(HttpServletRequest httpServletRequest, String openid, String orderNo, String price) {
//        String mapStr = "";
//        HashMap<String, String> params = new HashMap<>();
//        try {
////        **通过订单id可以拿到订单信息**
//            //获得openid调用微信统一下单接口
//            HashMap<String, String> dataMap = new HashMap<>();
//            dataMap.put("appid", appid); //公众账号ID
//            dataMap.put("mch_id", mchId); //商户号
//            dataMap.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串，长度要求在32位以内。
//            dataMap.put("body", "bubble"); //商品描述,通过订单id获得
//            dataMap.put("out_trade_no", orderNo); //商品订单号,用户下订单后台生成
//            dataMap.put("total_fee", price); //商品金,通过订单id获得
//            dataMap.put("spbill_create_ip", HttpUtils.getIpAddress(httpServletRequest)); //客户端ip
//            //通知地址(需要是外网可以访问的)
//            dataMap.put("notify_url", "http://bubble.renniyou.com.cn/api/order/notifyUrl");
//            dataMap.put("trade_type", "JSAPI"); //交易类型
//            dataMap.put("openid", openid);
//            //生成签名
//            String signature = WXPayUtil.generateSignature(dataMap, weixinKey);
//            dataMap.put("sign", signature);//签名
//            //将类型为map的参数转换为xml
//            String requestXml = WXPayUtil.mapToXml(dataMap);
//            System.out.println(requestXml);
//            //发送参数,调用微信统一下单接口,返回xml
//            String responseXml = HttpUtils.doPost(unifiedorderUrl, requestXml);
//            Map<String, String> responseMap = WXPayUtil.xmlToMap(responseXml);
//            System.out.println("ResponseMap:" + responseXml);
//            params.put("return_code", responseMap.get("return_code"));
//            if ("FAIL".equals(responseMap.get("return_code"))) {
//                mapStr = responseMap.get("return_msg");
//                params.put("return_code",mapStr);
//                return params;
//            }
//            if ("FAIL".equals(responseMap.get("result_code"))) {
//                mapStr = responseMap.get("err_code_des");
//                params.put("return_code",mapStr);
//                return params;
//            }
//            if ("".equals(responseMap.get("prepay_id")) || responseMap.get("prepay_id") ==
//                    null) {
//                params.put("return_code","prepay_id 为空");
//                return params;
//            }
//            //成功之后,提取prepay_id,重点就是这个
//
//            params.put("appId", appid);
//            params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
//            params.put("nonceStr", WXPayUtil.generateNonceStr());
//            params.put("package", "prepay_id="+responseMap.get("prepay_id"));
//            params.put("signType", WXPayConstants.MD5);
//
//            //重新签名
//            String paySign = WXPayUtil.generateSignature(params, weixinKey);
//            params.put("paySign", paySign);
//            //传给前端页面
//            //在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
//            mapStr = params.toString();
//            //前端接受参数调用wx.requestPayment(OBJECT)发起微信支付
//            //返回requestPayment:ok,支付成功
//        } catch (Exception e) {
//
//        }
//        return params;
//    }

    public static String notifyUrl(String unifiedorderUrl, String requestXml) {
        System.out.print("进入支付h5回调=====================");

        //判断接受到的result_code是不是SUCCESS,如果是,则返回成功,具体业务具体分析,修改订单状态

        // 通知微信.异步确认成功.必写.不然会一直通知后台.
        String resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" +
                "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        System.out.println(resXml);
        return resXml; //或者 return "success";
    }


//    public static Map<String, String> refund(Order order) throws Exception {
//        Map<String, String> params = new HashMap<>();
//        Integer price = order.getMoney().multiply(new BigDecimal(100)).intValue();
//
//        String outRefundNo = Long.toString(System.currentTimeMillis());
//        String refundMark = "退款备注";
//
//        params.put("appid", appid);
//        params.put("mch_id", mchId);
//        //商户订单号
//        params.put("out_trade_no", order.getOrderNo());
//        //商户退款单号
//        params.put("out_refund_no", outRefundNo);
//        //总金额
//        params.put("total_fee", price.toString());
//        //退款金额
//        params.put("refund_fee", price.toString());
//        //退款原因
//        params.put("refund_desc", refundMark);
//        //退款结果回调地址
//        /*params.put("notify_url", "");*/
//        //随机字符串
//        params.put("nonce_str", WXPayUtil.generateNonceStr());//使用微信随机字符串生成
//        //生成sign
//        String sign = WXPayUtil.generateSignature(params, weixinKey);
//        params.put("sign", sign);
//        //微信申请退款接口
//        String wx_refund_url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//
//        String xmlStr = WXPayUtil.mapToXml(params);//转换成xml格式
//        //发送双向证书请求给微信
//        String resultXmlStr = CertUtil.doRefund(wx_refund_url,xmlStr);
//
//        // 将返回的字符串转成Map集合
//        Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXmlStr);//转成map格式
//        System.out.println(resultMap);
//        Map<String, String> map = new HashMap<>();
//        if ("SUCCESS".equalsIgnoreCase(resultMap.get("result_code"))) {
//            System.out.println("------申请退款成功，正在退款中----");
//            //申请微信退款接口返回success，但是退款到账还需要时间；
//            map.put("success", "REFUNDS");
//        } else {
//            map.put("success", resultMap.get("err_code_des"));
//            System.out.println("------退款失败----{}" + resultMap.get("err_code_des"));
//        }
//        return map;
//    }

}